package controller;

import dtos.LeaveDTO;
import dtos.LeaveStatusDTO;
import dtos.LeaveTypeDTO;
import model.Leave;
import model.LeaveStatus;
import model.LeaveType;
import utils.Conv;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import java.util.ArrayList;
import java.util.List;

@Stateless
public class LeaveBean implements LeaveRemote {

    @PersistenceContext(unitName = "rmtPersistenceUnit")
    private EntityManager em;

    @EJB
    private Conv conv;

    @Override
    public LeaveDTO getLeaveById(int id) {
        return conv.toDtoLeave(getSingleLeave(id));
    }

    @Override
    public List<LeaveDTO> getLeaveByUserId(int uid) {
        List<Leave> leaves = em.createNamedQuery("Leave.getByUserId", Leave.class).setParameter("uid", uid).getResultList();
        List<LeaveDTO> leaveDTOs = new ArrayList<>();
        for (Leave l : leaves) {
            leaveDTOs.add(conv.toDtoLeave(l));
        }
        return leaveDTOs;
    }

    @Override
    public List<LeaveTypeDTO> getLeaveTypes() {
        List<LeaveType> leaveTypes = em.createNamedQuery("LeaveType.getLeaveTypes", LeaveType.class).getResultList();
        List<LeaveTypeDTO> leaveTypeDTOs = new ArrayList<>();
        for (LeaveType l : leaveTypes) {
            leaveTypeDTOs.add(conv.toDtoLeaveType(l));
        }
        return leaveTypeDTOs;
    }

    @Override
    public LeaveDTO saveLeave(LeaveDTO leaveDTO) {


        Leave leave = getSingleLeave(leaveDTO.getId());
        if (leave != null) {
            //update
            leave = conv.toEntityLeave(leaveDTO);
            leave = em.merge(leave);
        } else {
            //new
            leave = conv.toEntityLeave(leaveDTO);
            em.persist(leave);
        }
        em.flush();
        leaveDTO = conv.toDtoLeave(leave);
        return leaveDTO;
    }

    @Override
    public void deleteLeave(int id) {
        em.remove(em.find(Leave.class, id));
    }

    @Override
    public LeaveStatusDTO getStatusForNew() {
        return getLeaveStatusById(1);
    }

    @Override
    public List<LeaveDTO> getAllLeaves() {
        List<Leave> leaves = em.createNamedQuery("Leave.getAll", Leave.class).getResultList();
        List<LeaveDTO> leaveDTOs = new ArrayList<>();
        for (Leave l : leaves) {
            leaveDTOs.add(conv.toDtoLeave(l));
        }
        return leaveDTOs;
    }

    @Override
    public void approveLeave(int id) {
        setLeaveStatus(id, 2);
    }

    @Override
    public void declineLeave(int id) {
        setLeaveStatus(id, 3);
    }

    @Override
    public void setUnprocessedLeave(int id) {
        setLeaveStatus(id, 1);
    }

    private void setLeaveStatus(int id, int statusId) {
        LeaveStatus leaveStatus = em.find(LeaveStatus.class, statusId);
        Leave leave = em.find(Leave.class, id);
        leave.setStatus(leaveStatus);
        em.merge(leave);
    }

    @Override
    public LeaveStatusDTO getLeaveStatusById(int id) {
        TypedQuery<LeaveStatus> tq = em.createNamedQuery("LeaveStatus.getStatusById", LeaveStatus.class);
        tq.setParameter("id", id);
        LeaveStatus leaveStatus = tq.getSingleResult();
        return conv.toDtoLeaveStatus(leaveStatus);
    }

    @Override
    public LeaveTypeDTO getLeaveTypeById(int id) {
        TypedQuery<LeaveType> tq = em.createNamedQuery("LeaveType.getLeaveTypesById", LeaveType.class);
        tq.setParameter("id", id);
        LeaveType leaveType= tq.getSingleResult();
        return conv.toDtoLeaveType(leaveType);
    }

    private Leave getSingleLeave(int id) {
        try {
            TypedQuery<Leave> tq = em.createNamedQuery("Leave.getById", Leave.class).setParameter("id", id);

            return tq.getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }
}
